// the preferred way to communicate between threads
// push objects into a channel on one end and pop objects from the other end
// can be buffered or unbuffered
// it is possible to `select` from multiple channels
// no need to be declared as `mut`
// can be passed to threads like normal variables
// use the arrow operator to push/pop objects

ch := chan int{cap: 1}
ch2 := chan f64{cap: 1}
n := 5

// push
ch <- n
ch2 <- 7.3

mut y := f64(0.0)
m := <-ch // pop creating new variable
y = <-ch2 // pop into existing variable
println(m)
println(y)

// pushing to closed channels will result in a runtime panic(exception of select and try_push)
// attempts to pop will return immediately if the associated channel has been closed and the buffer is empty
ch3 := chan int{}
ch4 := chan f64{}
// ch4 := chan f64{cap: 1}
// ...
ch3.close()
// ...
m3 := <-ch3 or {
	println('channel has been closed')
}
ch4 <- 4.0 
y4 := <-ch4 ?
println(y4)
